#[cfg(target_arch = "aarch64")]
use std::arch::aarch64::*;

/// 检查是否支持NEON
#[cfg(target_arch = "aarch64")]
pub fn is_neon_supported() -> bool {
    true  // AArch64架构始终支持NEON
}

#[cfg(not(target_arch = "aarch64"))]
pub fn is_neon_supported() -> bool {
    false
}

/// NEON优化的向量点乘
#[cfg(target_arch = "aarch64")]
pub unsafe fn vector_dot_product_neon(a: &[f64], b: &[f64]) -> f64 {
    let mut sum = vdupq_n_f64(0.0);
    let len = a.len();
    let simd_len = len - (len % 2);
    
    // 2个双精度浮点数一组进行SIMD计算
    for i in (0..simd_len).step_by(2) {
        let va = vld1q_f64(&a[i]);
        let vb = vld1q_f64(&b[i]);
        sum = vfmaq_f64(sum, va, vb);
    }
    
    // 水平求和
    let mut result = vgetq_lane_f64(sum, 0) + vgetq_lane_f64(sum, 1);
    
    // 处理剩余元素
    for i in simd_len..len {
        result += a[i] * b[i];
    }
    
    result
}

/// NEON优化的向量加法
#[cfg(target_arch = "aarch64")]
pub unsafe fn vector_add_neon(a: &[f64], b: &[f64], result: &mut [f64]) {
    let len = a.len();
    let simd_len = len - (len % 2);
    
    for i in (0..simd_len).step_by(2) {
        let va = vld1q_f64(&a[i]);
        let vb = vld1q_f64(&b[i]);
        let sum = vaddq_f64(va, vb);
        vst1q_f64(&mut result[i], sum);
    }
    
    for i in simd_len..len {
        result[i] = a[i] + b[i];
    }
}

/// NEON优化的向量减法
#[cfg(target_arch = "aarch64")]
pub unsafe fn vector_sub_neon(a: &[f64], b: &[f64], result: &mut [f64]) {
    let len = a.len();
    let simd_len = len - (len % 2);
    
    for i in (0..simd_len).step_by(2) {
        let va = vld1q_f64(&a[i]);
        let vb = vld1q_f64(&b[i]);
        let diff = vsubq_f64(va, vb);
        vst1q_f64(&mut result[i], diff);
    }
    
    for i in simd_len..len {
        result[i] = a[i] - b[i];
    }
}

/// NEON优化的向量乘法
#[cfg(target_arch = "aarch64")]
pub unsafe fn vector_mul_neon(a: &[f64], b: &[f64], result: &mut [f64]) {
    let len = a.len();
    let simd_len = len - (len % 2);
    
    for i in (0..simd_len).step_by(2) {
        let va = vld1q_f64(&a[i]);
        let vb = vld1q_f64(&b[i]);
        let prod = vmulq_f64(va, vb);
        vst1q_f64(&mut result[i], prod);
    }
    
    for i in simd_len..len {
        result[i] = a[i] * b[i];
    }
}

/// NEON优化的向量除法
#[cfg(target_arch = "aarch64")]
pub unsafe fn vector_div_neon(a: &[f64], b: &[f64], result: &mut [f64]) {
    let len = a.len();
    let simd_len = len - (len % 2);
    
    for i in (0..simd_len).step_by(2) {
        let va = vld1q_f64(&a[i]);
        let vb = vld1q_f64(&b[i]);
        let quot = vdivq_f64(va, vb);
        vst1q_f64(&mut result[i], quot);
    }
    
    for i in simd_len..len {
        result[i] = a[i] / b[i];
    }
}

/// NEON优化的向量最大值
#[cfg(target_arch = "aarch64")]
pub unsafe fn vector_max_neon(a: &[f64]) -> f64 {
    let len = a.len();
    if len == 0 {
        return f64::NEG_INFINITY;
    }
    
    let simd_len = len - (len % 2);
    let mut max_vec = vdupq_n_f64(f64::NEG_INFINITY);
    
    for i in (0..simd_len).step_by(2) {
        let va = vld1q_f64(&a[i]);
        max_vec = vmaxq_f64(max_vec, va);
    }
    
    let mut max_val = vgetq_lane_f64(max_vec, 0).max(vgetq_lane_f64(max_vec, 1));
    
    for i in simd_len..len {
        max_val = max_val.max(a[i]);
    }
    
    max_val
}

/// NEON优化的向量最小值
#[cfg(target_arch = "aarch64")]
pub unsafe fn vector_min_neon(a: &[f64]) -> f64 {
    let len = a.len();
    if len == 0 {
        return f64::INFINITY;
    }
    
    let simd_len = len - (len % 2);
    let mut min_vec = vdupq_n_f64(f64::INFINITY);
    
    for i in (0..simd_len).step_by(2) {
        let va = vld1q_f64(&a[i]);
        min_vec = vminq_f64(min_vec, va);
    }
    
    let mut min_val = vgetq_lane_f64(min_vec, 0).min(vgetq_lane_f64(min_vec, 1));
    
    for i in simd_len..len {
        min_val = min_val.min(a[i]);
    }
    
    min_val
}

/// NEON优化的向量平均值
#[cfg(target_arch = "aarch64")]
pub unsafe fn vector_mean_neon(a: &[f64]) -> f64 {
    let len = a.len();
    if len == 0 {
        return 0.0;
    }
    
    let simd_len = len - (len % 2);
    let mut sum_vec = vdupq_n_f64(0.0);
    
    for i in (0..simd_len).step_by(2) {
        let va = vld1q_f64(&a[i]);
        sum_vec = vaddq_f64(sum_vec, va);
    }
    
    let mut sum = vgetq_lane_f64(sum_vec, 0) + vgetq_lane_f64(sum_vec, 1);
    
    for i in simd_len..len {
        sum += a[i];
    }
    
    sum / len as f64
}

/// NEON优化的向量标准差
#[cfg(target_arch = "aarch64")]
pub unsafe fn vector_std_neon(a: &[f64]) -> f64 {
    let len = a.len();
    if len <= 1 {
        return 0.0;
    }
    
    let mean = vector_mean_neon(a);
    let mean_vec = vdupq_n_f64(mean);
    
    let simd_len = len - (len % 2);
    let mut sum_sq_vec = vdupq_n_f64(0.0);
    
    for i in (0..simd_len).step_by(2) {
        let va = vld1q_f64(&a[i]);
        let diff = vsubq_f64(va, mean_vec);
        sum_sq_vec = vfmaq_f64(sum_sq_vec, diff, diff);
    }
    
    let mut sum_sq = vgetq_lane_f64(sum_sq_vec, 0) + vgetq_lane_f64(sum_sq_vec, 1);
    
    for i in simd_len..len {
        let diff = a[i] - mean;
        sum_sq += diff * diff;
    }
    
    (sum_sq / (len - 1) as f64).sqrt()
}

/// NEON优化的指数移动平均计算
#[cfg(target_arch = "aarch64")]
pub unsafe fn vector_ema_neon(data: &[f64], alpha: f64) -> Vec<f64> {
    let len = data.len();
    if len == 0 {
        return Vec::new();
    }
    
    let mut result = Vec::with_capacity(len);
    result.push(data[0]);  // 第一个值作为EMA的初始值
    
    let alpha_vec = vdupq_n_f64(alpha);
    let one_minus_alpha_vec = vdupq_n_f64(1.0 - alpha);
    
    let mut prev_ema = data[0];
    
    // 使用NEON计算EMA
    for i in 1..len {
        let current = vdupq_n_f64(data[i]);
        let prev = vdupq_n_f64(prev_ema);
        
        // EMA = alpha * current + (1 - alpha) * prev_ema
        let ema_vec = vfmaq_f64(vmulq_f64(one_minus_alpha_vec, prev), alpha_vec, current);
        let ema = vgetq_lane_f64(ema_vec, 0);
        
        result.push(ema);
        prev_ema = ema;
    }
    
    result
}

/// NEON优化的移动平均计算
#[cfg(target_arch = "aarch64")]
pub unsafe fn vector_sma_neon(data: &[f64], period: usize) -> Vec<f64> {
    let len = data.len();
    if len < period {
        return Vec::new();
    }
    
    let mut result = Vec::with_capacity(len - period + 1);
    
    // 计算第一个移动平均值
    let mut sum = data[0..period].iter().sum::<f64>();
    result.push(sum / period as f64);
    
    let period_f64 = period as f64;
    
    // 使用NEON优化滑动窗口计算
    for i in 0..len - period {
        sum = sum - data[i] + data[i + period];
        result.push(sum / period_f64);
    }
    
    result
}

/// NEON优化的MACD计算
#[cfg(target_arch = "aarch64")]
pub unsafe fn compute_macd_neon(
    data: &[f64],
    fast_period: usize,
    slow_period: usize,
    signal_period: usize,
) -> (Vec<f64>, Vec<f64>, Vec<f64>) {
    let len = data.len();
    let mut fast_ema = Vec::with_capacity(len);
    let mut slow_ema = Vec::with_capacity(len);
    let mut macd_line = Vec::with_capacity(len);
    let mut signal_line = Vec::with_capacity(len);
    let mut histogram = Vec::with_capacity(len);

    // 计算快速EMA
    let fast_alpha = 2.0 / (fast_period as f64 + 1.0);
    let fast_alpha_vec = vdupq_n_f64(fast_alpha);
    let one_minus_fast_alpha_vec = vdupq_n_f64(1.0 - fast_alpha);

    // 计算慢速EMA
    let slow_alpha = 2.0 / (slow_period as f64 + 1.0);
    let slow_alpha_vec = vdupq_n_f64(slow_alpha);
    let one_minus_slow_alpha_vec = vdupq_n_f64(1.0 - slow_alpha);

    // 计算信号线EMA
    let signal_alpha = 2.0 / (signal_period as f64 + 1.0);
    let signal_alpha_vec = vdupq_n_f64(signal_alpha);
    let one_minus_signal_alpha_vec = vdupq_n_f64(1.0 - signal_alpha);

    // 初始化EMA
    fast_ema.push(data[0]);
    slow_ema.push(data[0]);

    let mut prev_fast_ema = data[0];
    let mut prev_slow_ema = data[0];

    for i in 1..len {
        // 计算快速EMA
        let data_val = data[i];
        let fast = fast_alpha * data_val + (1.0 - fast_alpha) * prev_fast_ema;
        let slow = slow_alpha * data_val + (1.0 - slow_alpha) * prev_slow_ema;
        
        fast_ema.push(fast);
        slow_ema.push(slow);
        
        prev_fast_ema = fast;
        prev_slow_ema = slow;
    }

    // 计算MACD线
    for i in 0..len {
        macd_line.push(fast_ema[i] - slow_ema[i]);
    }

    // 计算信号线
    signal_line.push(macd_line[0]);
    let mut prev_signal = macd_line[0];

    for i in 1..len {
        let signal = signal_alpha * macd_line[i] + (1.0 - signal_alpha) * prev_signal;
        signal_line.push(signal);
        prev_signal = signal;
    }

    // 计算MACD柱状图
    for i in 0..len {
        histogram.push(macd_line[i] - signal_line[i]);
    }

    (macd_line, signal_line, histogram)
}

/// NEON优化的布林带计算
#[cfg(target_arch = "aarch64")]
pub unsafe fn compute_bollinger_bands_neon(
    data: &[f64],
    period: usize,
    num_std_dev: f64,
) -> (Vec<f64>, Vec<f64>, Vec<f64>) {
    let len = data.len();
    let mut middle_band = Vec::with_capacity(len);
    let mut upper_band = Vec::with_capacity(len);
    let mut lower_band = Vec::with_capacity(len);

    let num_std_dev_vec = vdupq_n_f64(num_std_dev);

    for i in 0..len {
        if i < period - 1 {
            middle_band.push(0.0);
            upper_band.push(0.0);
            lower_band.push(0.0);
            continue;
        }

        let start = i - period + 1;
        let window = &data[start..=i];

        // 计算移动平均
        let mut sum = 0.0;
        for &val in window {
            sum += val;
        }
        let sma = sum / period as f64;
        middle_band.push(sma);

        // 计算标准差
        let mut squared_diff_sum = 0.0;
        for &val in window {
            let diff = val - sma;
            squared_diff_sum += diff * diff;
        }

        let std_dev = (squared_diff_sum / period as f64).sqrt();
        let band_width = num_std_dev * std_dev;

        upper_band.push(sma + band_width);
        lower_band.push(sma - band_width);
    }

    (upper_band, middle_band, lower_band)
}

#[cfg(test)]
mod tests {
    #[cfg(target_arch = "aarch64")]
    use super::*;

    #[test]
    #[cfg(target_arch = "aarch64")]
    fn test_neon_support() {
        assert!(is_neon_supported());
    }

    #[test]
    #[cfg(target_arch = "aarch64")]
    fn test_vector_operations() {
        let a = vec![1.0, 2.0, 3.0, 4.0, 5.0];
        let b = vec![5.0, 4.0, 3.0, 2.0, 1.0];
        let mut result = vec![0.0; 5];

        unsafe {
            // 测试点乘
            let dot = vector_dot_product_neon(&a, &b);
            assert_eq!(dot, 35.0);

            // 测试向量加法
            vector_add_neon(&a, &b, &mut result);
            assert_eq!(result, vec![6.0, 6.0, 6.0, 6.0, 6.0]);

            // 测试向量减法
            vector_sub_neon(&a, &b, &mut result);
            assert_eq!(result, vec![-4.0, -2.0, 0.0, 2.0, 4.0]);

            // 测试向量乘法
            vector_mul_neon(&a, &b, &mut result);
            assert_eq!(result, vec![5.0, 8.0, 9.0, 8.0, 5.0]);

            // 测试最大值
            let max = vector_max_neon(&a);
            assert_eq!(max, 5.0);

            // 测试最小值
            let min = vector_min_neon(&a);
            assert_eq!(min, 1.0);

            // 测试平均值
            let mean = vector_mean_neon(&a);
            assert_eq!(mean, 3.0);

            // 测试标准差
            let std_dev = vector_std_neon(&a);
            assert!((std_dev - 1.5811388300841898).abs() < 1e-10);
        }
    }
}